﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
using System.Text;
using SCRUM.Core.BusinessObjects;
using SCRUM.Core.DAO;
using SCRUM.Core.MembershipProviders;

/// <summary>
/// Interface for all widget used on dashboard
/// </summary>
public abstract class WidgetBase : UserControl
{
    /// <summary>
    /// Gets or sets the programmatic identifier assigned to the server control.
    /// </summary>
    /// <value></value>
    /// <returns>
    /// The programmatic identifier assigned to the control.
    /// </returns>
    public int ID
    {
        get
        {
            if (ViewState["WidgetID"] == null)
            {
                throw new ViewStateException();
            }
            return (int)ViewState["WidgetID"];
        }
        set
        {
            ViewState["WidgetID"] = value;
        }
    }

    /// <summary>
    /// Gets or sets the programmatic identifier assigned to type of the widget.
    /// </summary>
    /// <value>The type ID.</value>
    public int TypeID { get; set; }
    //public int TypeID
    //{
    //    get
    //    {
    //        if (ViewState["WidgetTypeID"]==null)
    //        {
    //            throw new ViewStateException();
    //        }
    //        return (int)ViewState["WidgetTypeID"];
    //    }
    //    set
    //    {
    //        ViewState["WidgetTypeID"] = value;
    //    }
    //}

    /// <summary>
    /// Gets the name of the widget. It must be exactly the same as the folder that contains the widget.
    /// </summary>
    public abstract string Name { get; }

    /// <summary>
    /// Gets the title. Title is shown in the header of the widget container.
    /// </summary>
    /// <value>The title.</value>
    public abstract string Title { get; }

    /// <summary>
    /// Gets a value indicating whether this instance is editable.
    /// </summary>
    /// <value>
    /// 	<c>true</c> if this instance is editable; otherwise, <c>false</c>.
    /// </value>
    public virtual bool IsEditable { get{return false;} }

    /// <summary>
    /// This method works as a substitute for Page_Load. You should use this method for
    /// data binding etc. instead of Page_Load.
    /// </summary>
    public abstract void LoadWidget();

    /// <summary>
    /// Gets the settings.
    /// </summary>
    /// <returns></returns>
    public StringDictionary GetSettings()
    {
        Widget widget = DAOWidget.GetWidgetByID(this.ID);
        StringDictionary settings = DAOWidgetSettings.LoadSettings(widget);
        if (settings.Count == 0)
        {
            settings = GetDefaultSettings();
            DAOWidgetSettings.SaveDefaultSettings(widget, settings);
            //settings = DAOWidgetSettings.LoadSettings(widget);
        }
        return settings;
    }

    public virtual StringDictionary GetDefaultSettings()
    {
        return new StringDictionary();
    }

    /// <summary>
    /// Saves the default settings if not present in db (UPDATE STATEMENTS).
    /// </summary>
    /// <param name="settings">The settings.</param>
    public void SaveSettings(StringDictionary settings)
    {
        Widget widget = DAOWidget.GetWidgetByID(this.ID);

        DAOWidgetSettings.SaveSettings(widget, settings);
    }

    /// <summary>
    /// Saves user's settings (INSERT STATEMENTS).
    /// </summary>
    /// <param name="settings">The settings.</param>
    public void SaveDefaultSettings(StringDictionary settings)
    {
        Widget widget = DAOWidget.GetWidgetByID(this.ID);

        DAOWidgetSettings.SaveDefaultSettings(widget, settings);
    }

    /// <summary>
    /// Renders the widget content
    /// </summary>
    /// <param name="writer">Writer</param>
    protected override void Render(HtmlTextWriter writer)
    {
        if (String.IsNullOrEmpty(this.Name))
            throw new NullReferenceException("Name must be set on a widget");
        base.Render(writer);
    }

    /// <summary>
    /// Occurs when [edit showed].
    /// </summary>
    public event EventHandler EditShowed;

    /// <summary>
    /// Occurs when [edit hided].
    /// </summary>
    public event EventHandler EditHidden;

    /// <summary>
    /// Called when [edit showed].
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    public void OnEditShowed(object sender, EventArgs e)
    {
        if (this.EditShowed != null)
        {
            this.EditShowed(this, e);
        }
    }

    /// <summary>
    /// Called when [edit hidden].
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    public void OnEditHidden(object sender, EventArgs e)
    {
        if (this.EditHidden != null)
        {
            this.EditHidden(this, e);
        }
    }

    /// <summary>
    /// Shows the edit.
    /// </summary>
    public virtual void ShowEdit()
    {
        this.EditShowed(this, new EventArgs());
    }

    /// <summary>
    /// Hides the edit.
    /// </summary>
    public virtual void HideEdit()
    {
        this.EditHidden(this, new EventArgs());
    }

    #region [ Showing operation results ]

    /// <summary>
    /// Type of message to display
    /// </summary>
    public enum MessageType
    {
        /// <summary>
        /// Information is displayed
        /// </summary>
        Info,
        /// <summary>
        /// Warning is displayed
        /// </summary>
        Warning,
        /// <summary>
        /// Error is displayed
        /// </summary>
        Error
    }

    /// <summary>
    /// Delegate for showing message after some operation.
    /// </summary>
    public delegate void OperationDelegate(MessageType type, string message, bool localize);

    /// <summary>
    /// Delegate for showing message after some operation with parameters.
    /// </summary>
    public delegate void ParametrizedOperationDelegate(MessageType type, string message, params object[] parameters);

    /// <summary>
    /// Occurs when operation occurs.
    /// </summary>
    public event OperationDelegate OnOperation;

    /// <summary>
    /// Occurs when parametrized operation occurs.
    /// </summary>
    public event ParametrizedOperationDelegate OnParametrizedOperation;

    /// <summary>
    /// Shows the operation projects.
    /// </summary>
    /// <param name="message">The message.</param>
    public void ShowOperationResult(MessageType type, string message)
    {
        if (this.OnOperation != null)
        {
            this.OnOperation(type, message, true);
        }
    }

	public void ShowRawOperationResult(MessageType type, string message)
	{
		if (this.OnOperation != null)
		{
			this.OnOperation(type, message, false);
		}
	}

    /// <summary>
    /// Shows the operation projects.
    /// </summary>
    /// <param name="message">The message.</param>
    /// <param name="parameters">The parameters.</param>
    public void ShowOperationResult(MessageType type, string message, params object[] parameters)
    {
        if (this.OnParametrizedOperation != null)
        {
            this.OnParametrizedOperation(type, message, parameters);
        }
    }

    #endregion

    #region [ WIDGET RIGHTS ]

    public UserRightForWidget UserRights 
    {
        get
        {
            if (userRights == null)
            {
                User currentUser = MembershipProviderFactory.MembershipProvider.GetUser();
                userRights = DAOWidgetRight.GetUserRightForWidget(currentUser.ID, this.TypeID);
            }
            return userRights;
        }

    }
    private UserRightForWidget userRights;

    protected void Page_Load(object sender, EventArgs e)
    {
        this.ReadOnly = !this.UserRights.CanModify;
        SecureWidgetRights();
    }

    protected void SecureWidgetRights()
    {
        if (!this.UserRights.CanSee)
        {
            ShowOperationResult(MessageType.Warning, "CannotSeeWidget");
            this.Visible = false;
        }
        else if (!this.UserRights.CanModify)
        {
            ShowOperationResult(MessageType.Warning, "ReadOnlyWidget");
        }
        //this.ReadOnly = !this.UserRights.CanModify;
    }

    /// <summary>
    /// Sets a value indicating whether read only.
    /// </summary>
    /// <value><c>true</c> if [read only]; otherwise, <c>false</c>.</value>
    public virtual bool ReadOnly 
    {
        set { }
        get
        {
            return !(this.UserRights.CanModify);
        }
        //set { this._readonly = value; }
        //get { return this.UserRights.CanModify;}
        //get { return this._readonly; }
    }
    private bool _readonly = false;

    #endregion
}
